package com.qigao.mall.channel.weichat;

import com.qigao.mall.channel.config.ChannelConstant;
import com.qigao.mall.commons.dto.MerChannelDto;
import com.qigao.mall.commons.enums.ChannelCodeEnum;
import com.qigao.mall.commons.enums.StreamFormatEnum;
import com.qigao.mall.commons.param.ChannelReqParam;
import com.qigao.mall.commons.param.ChannelRespParam;
import com.qigao.mall.commons.utils.HttpClientUtil;
import com.qigao.mall.commons.utils.PayUtil;
import com.qigao.mall.commons.utils.XMLUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.JDOMException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 文档链接：https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1
 */
@Service
public abstract  class AbstractWeichatTrade {

    @Resource
    ChannelConstant channelConstant;
    private static final Logger logger= LoggerFactory.getLogger(WeiChatJsapiPay.class);

    public ChannelRespParam channelProcess(MerChannelDto merChannelDto, ChannelReqParam channelReqParam) {
        //1.构造请求参数
        String reqContent=buildReqParam(merChannelDto,channelReqParam);
        //2.发送请求
        String reqUrl=getSelfReqUrl()==null?channelConstant.getWeichatOrderUrl():getSelfReqUrl();
        String respContent= HttpClientUtil.doPostStr(reqUrl,reqContent);
        logger.info("[微信交易]返回内容:{}",respContent);
        //3.处理响应
        ChannelRespParam channelRespParam=convertRespData(respContent,merChannelDto);
        logger.info("[微信交易]返回转换后内容:{}",channelRespParam);
        //3.处理响应
        return channelRespParam;
    }

    /**
     * 获取请求地址
     * @return
     */
    protected abstract String getSelfReqUrl();

    protected ChannelRespParam convertRespData(String respContent, MerChannelDto merChannelDto) {
        ChannelRespParam channelRespParam=new ChannelRespParam();
        channelRespParam.setRespCode(ChannelCodeEnum.SUCCESS.getCode());
        channelRespParam.setRespMsg(ChannelCodeEnum.SUCCESS.getName());
        try{
            if(StringUtils.isEmpty(respContent)){
                channelRespParam.setRespCode(ChannelCodeEnum.RESP_NULL.getCode());
                channelRespParam.setRespCode(ChannelCodeEnum.RESP_NULL.getName());
                return channelRespParam;
            }
            Map respMap=XMLUtil.doXMLParse(respContent);
            String retSign=(String) respMap.get("sign");
            respMap.remove("sign");
            //1.状态码判断
            String returnCode=(String) respMap.get("return_code");
            if(!"SUCCESS".equals(returnCode)){
                channelRespParam.setRespCode(ChannelCodeEnum.FAIL.getCode());
                channelRespParam.setRespMsg((String) respMap.get("return_msg"));
                return channelRespParam;
            }
            //2. 签名验证
            String sysSign= PayUtil.createSign(respMap,merChannelDto.getSignType(),merChannelDto.getMd5Key());
            if(ObjectUtils.notEqual(sysSign,retSign)){
                channelRespParam.setRespCode(ChannelCodeEnum.SIGN_VALID_FAIL.getCode());
                channelRespParam.setRespCode(ChannelCodeEnum.SIGN_VALID_FAIL.getName());
                return channelRespParam;
            }
            String resultCode=(String) respMap.get("result_code");
            if(!"SUCCESS".equals(resultCode)){
                channelRespParam.setRespCode(ChannelCodeEnum.FAIL.getCode());
                channelRespParam.setRespMsg((String) respMap.get("err_code_des"));
                return channelRespParam;
            }
            //3.返回参数封装
            channelRespParam = buildSelfRespData(respMap,merChannelDto);

        }catch (IOException | JDOMException ioException){
            channelRespParam.setRespCode(ChannelCodeEnum.PARSE_FAIL.getCode());
            channelRespParam.setRespMsg(ChannelCodeEnum.PARSE_FAIL.getName());
        }
        return channelRespParam;
    }



    public  String buildReqParam(MerChannelDto merChannelDto, ChannelReqParam channelReqParam) {
        Map reqParam=new ConcurrentHashMap<String,String>();
        reqParam.put("appid", merChannelDto.getAppId());
        reqParam.put("mch_id", merChannelDto.getChannelPartenerNo());
        reqParam.put("nonce_str", PayUtil.getRandomString(16));
        //构造自定义参数
        reqParam.putAll(buildSelfReqParam(merChannelDto,channelReqParam));
        String signValue= PayUtil.createSign(reqParam,merChannelDto.getSignType(),merChannelDto.getMd5Key());
        reqParam.put("sign",signValue);
        //返回请求微信方的xml参数
        return PayUtil.mapToXml(reqParam);
    }

    /**
     * 构造自定义请求参数
     * @param merChannelDto
     * @param channelReqParam
     * @return
     */
    public abstract Map buildSelfReqParam(MerChannelDto merChannelDto, ChannelReqParam channelReqParam);


    /**
     * 构造自定义返回参数
     * @param respMap
     * @return
     */
    protected abstract ChannelRespParam buildSelfRespData(Map respMap,MerChannelDto merChannelDto);


}
